package com.huitongjy.common.zookeeper;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.DecimalFormat;
import java.util.Comparator;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;

/**
 * 工作Id生成器
 * @author guan
 */
public class ZooKeeperWorkId {
    private static final String PATH_SYSTEM = "/www/worker/system";
    private static final String PATH_GLOBAL = "/www/worker/global";

    /**
     * 项目内私有的workerId
     */
    private Long workerId;
    /**
     * 项目间通用的workerId
     */
    private Long globalWorkerId;

    /**
     * zookeeper地址
     */
    private String address;

    /**
     * 项目
     */
    private String nodeName;

    private ZooKeeperWorkId(String address, String nodeName) {
        this.address = address;
        this.nodeName = nodeName;
    }

    private static ZooKeeperWorkId INSTANCE;

    public static synchronized ZooKeeperWorkId getInstanse() {
        if(INSTANCE==null) {
            Properties properties = new Properties();
            try {
                //项目使用dubbo的zookeeer配置
                InputStream resourceAsStream = ZooKeeperWorkId.class.getClassLoader().getResourceAsStream("dubbo.properties");
                if(resourceAsStream==null) {
                    throw new RuntimeException("主键生成配置不存在");
                }

                properties.load(resourceAsStream);

                String address = (String) properties.get("dubbo.registry.address");
                String nodeName = (String) properties.get("dubbo.application.name");
                if(address==null || nodeName ==null) {
                    throw new RuntimeException("主键生成配置不存在");
                }
                INSTANCE = new ZooKeeperWorkId(address, nodeName);
            } catch (IOException ignore) {
                throw new RuntimeException("主键生成器配置不存在");
            }
        }
        return INSTANCE;
    }

    public long getWorkerId() {
        if(workerId==null) {
            try {
                // init workerId
                workerId = getZookeeperWorkerId(false);
                System.out.println("当前工作节点:"+workerId);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return workerId;
    }

    public long getGlobalWorkerId() {
        if(globalWorkerId==null) {
            try {
                // init global workerId
                globalWorkerId = getZookeeperWorkerId(true);
                System.out.println("当前工作节点(global):"+globalWorkerId);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return globalWorkerId;
    }


    /**
     * 获取一个自增的机器Id (项目|host)唯一, 如果没有则生成
     * @param isGlobal 全局
     * @return
     * @throws KeeperException
     * @throws InterruptedException
     */
    private Long getZookeeperWorkerId(boolean isGlobal) {
        String nodePath = getNodePath(isGlobal);
        String workerIdPath = getWorkerIdPath(isGlobal);

        try (ZookeeperClient client = new ZookeeperClient(address)) {
            return client.getZookeeperWorkerId(nodePath, workerIdPath);
        }
    }

    /**
     * 获取workId所在目录
     * @param isGolbal
     * @return
     */
    private String getWorkerIdPath(boolean isGolbal) {
        if(isGolbal) {
            return PATH_GLOBAL + "/" + "workerId";
        }
        return PATH_SYSTEM + "/" + nodeName + "/" + "workerId";
    }

    /**
     * 获取节点所在目录
     * @param isGolbal
     * @return
     */
    private String getNodePath(boolean isGolbal) {
        if(isGolbal) {
            return PATH_GLOBAL + "/" + nodeName;
        }
        return PATH_SYSTEM + "/" + nodeName;
    }

}
